package cn.xerllent.wxtp.rest;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.pagehelper.PageHelper;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.xerllent.common.annotation.AnonymousAccess;
import cn.xerllent.common.annotation.ForbidSubmit;
import cn.xerllent.common.annotation.Log;
import cn.xerllent.common.entity.vo.OffsetPageable;
import cn.xerllent.common.entity.vo.ResultData;
import cn.xerllent.common.exception.BadRequestException;
import cn.xerllent.common.utils.SecurityUtils;
import cn.xerllent.security.oauth2.WxTpAuthenticationToken;
import cn.xerllent.security.security.TokenUtil;
import cn.xerllent.security.security.vo.JwtUser;
import cn.xerllent.security.service.OnlineUserService;
import cn.xerllent.wxtp.config.WxCpTpConfiguration;
import cn.xerllent.wxtp.entity.Dksb;
import cn.xerllent.wxtp.entity.DksbCourse;
import cn.xerllent.wxtp.entity.WxReport;
import cn.xerllent.wxtp.entity.WxUser;
import cn.xerllent.wxtp.service.DksbCourseService;
import cn.xerllent.wxtp.service.DksbReportService;
import cn.xerllent.wxtp.service.DksbService;
import cn.xerllent.wxtp.service.WxUserService;
import cn.xerllent.wxtp.service.dto.DksbFilter;
import cn.xerllent.wxtp.utils.DksbConsts;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpTpUserDetail;
import me.chanjar.weixin.cp.bean.WxCpTpUserInfo;
import me.chanjar.weixin.cp.tp.service.WxCpTpService;

/**
 * 企业微信：代课申报专用接口
 */
@Slf4j
@RestController
@RequestMapping("/wxtp/dksb/api/dksb")
public class DksbController {

	private final WxUserService wxUserService;
	private final DksbService dksbService;
	private final DksbCourseService dksbCourseService;
	private final DksbReportService dksbReportService;
	private final WxCpTpService tpService;
	
	@Autowired
	@Qualifier("singleThreadExecutor")
	private ExecutorService singleThreadExecutor;

	public DksbController(WxUserService wxUserService,DksbService dksbService,DksbReportService dksbReportService, DksbCourseService dksbCourseService) {
		super();
		this.wxUserService = wxUserService;
		this.dksbService = dksbService;
		this.dksbCourseService = dksbCourseService;
		this.dksbReportService = dksbReportService;
		this.tpService = WxCpTpConfiguration.getCpTpService("dksb");
	}

    @Log("导出申报数据")
    @ApiOperation("导出申报数据")
    @GetMapping(value = "/download")
    public void download(HttpServletResponse response, DksbFilter filter) throws IOException {
    	dksbService.download(dksbService.queryAll(filter), response);
    }

    @Log("查询申报,移动端偏移量分页模式")
    @ApiOperation("查询申报,移动端偏移量分页模式")
    @GetMapping
//    @AnonymousAccess
    public ResponseEntity<Object> getDksbs(DksbFilter filter,OffsetPageable offsetPageable) {
        return new ResponseEntity<>(ResultData.data(dksbService.queryAll(filter, offsetPageable)), HttpStatus.OK);
    }
    
    @Log("查询代课明细,移动端偏移量分页模式")
    @ApiOperation("查询代课明细,移动端偏移量分页模式")
    @GetMapping(value = "/course")
    public ResponseEntity<Object> getDksbCourses(DksbFilter filter,OffsetPageable offsetPageable) {
        return new ResponseEntity<>(ResultData.data(dksbCourseService.queryAll(filter, offsetPageable)), HttpStatus.OK);
    }
    
    @Log("获取下载报表，移动端偏移量分页模式")
    @ApiOperation("获取下载报表，移动端偏移量分页模式")
    @GetMapping(value = "/report")
    public ResponseEntity<Object> getReport(WxReport filter,OffsetPageable offsetPageable) {
    	JwtUser jwtUser = (JwtUser) wxUserService.loadUserByUsername(SecurityUtils.getUsername());
    	filter.setSuiteId(tpService.getWxCpTpConfigStorage().getSuiteId()).setUserid(jwtUser.getUserId());
    	return new ResponseEntity<>(ResultData.data(dksbReportService.queryAll(filter, offsetPageable)), HttpStatus.OK);
    }
    
    @Log("根据查询参数生成下载报表")
    @ApiOperation("根据查询参数生成下载报表")
    @PostMapping(value = "/report")
    public ResponseEntity<Object> createReport(@RequestBody DksbFilter filter ) {
    	//1保存数据库
    	JwtUser jwtUser = (JwtUser) wxUserService.loadUserByUsername(SecurityUtils.getUsername());
    	WxReport r = new WxReport()
    			.setCorpId(filter.getCorpId())
    			.setSuiteId(tpService.getWxCpTpConfigStorage().getSuiteId())
    			.setType("0")
    			.setTitle(filter.getTitle())
    			.setParams(filter.toJson())
    			.setUserid(jwtUser.getUserId())
    			.setStatus(0);
    	dksbReportService.save(r);
    	
    	//改善性能，利用单线程任务执行
		singleThreadExecutor.execute(new Runnable() { 
			@Override
			public void run() {
		    	//2生成报表文件
		    	//3上传媒体
		    	//4执行id转译
		    	//5回调
				dksbReportService.createReport(r, tpService);
			}
		});
        return new ResponseEntity<>(HttpStatus.OK);
    }
    
    @Log("根据旧查询参数重新生成下载报表")
    @ApiOperation("根据旧查询参数重新生成下载报表")
    @PutMapping(value = "/report")
    public ResponseEntity<Object> reCreateReport(@RequestParam Long id) {
    	//1,重置并保存数据库
    	final WxReport r = dksbReportService.getById(id);
    	r.setCreatetime(LocalDateTime.now())
    	.setStatus(0)
    	.setUrl(null)
    	.setDonetime(null)
    	.setFilepath(null)
    	.setMediaId(null);
    	dksbReportService.saveOrUpdate(r);
    	//改善性能，利用单线程任务执行
		singleThreadExecutor.execute(new Runnable() { 
			@Override
			public void run() {
		    	//2生成报表文件
		    	//3上传媒体
		    	//4执行id转译
		    	//5回调
				dksbReportService.createReport(r, tpService);
			}
		});
    	
        return new ResponseEntity<>(HttpStatus.OK);
    }
    
    @Log("删除报表")
    @ApiOperation("删除报表")
    @DeleteMapping(value = "/report")
    public ResponseEntity<Object> deleteReport(@RequestBody Set<Integer> ids) {
    	dksbReportService.removeByIds(ids);
        return new ResponseEntity<>(HttpStatus.OK);
    }
    
    @Log("获取指定流程号thirdNo的申报")
    @ApiOperation("获取指定流程号thirdNo的申报")
    @GetMapping(value="/{thirdNo}")
    //@AnonymousAccess
    public ResponseEntity<Object> getDksb(@PathVariable String thirdNo) {
    	Dksb dksb = dksbService.getOne(new LambdaQueryWrapper<Dksb>().eq(Dksb::getThirdNo, thirdNo));
        if(dksb == null) throw new BadRequestException("申报记录不存在");
        dksb.setCourses(dksbCourseService.list(new LambdaQueryWrapper<DksbCourse>().eq(DksbCourse::getDksbId, dksb.getId())));
        return new ResponseEntity<>(ResultData.data(dksb), HttpStatus.OK);
    }
    
    @Log("检查申报重复:提交流程操作前检查")
    @ApiOperation("检查申报重复:提交流程操作前检查")
    @PostMapping(value="/checkRepeat")
    //@AnonymousAccess
    public ResponseEntity<Object> checkRepeat(@Validated @RequestBody Dksb resources) {
    	//检查重复申报，不能跟提交的，审批中,审批通过的有重复 0-未提交；1-审批中；2-已通过；3-已驳回；4-已取消
    	for(DksbCourse course: resources.getCourses()) {
    		DksbCourse c = dksbCourseService.checkRepeat(resources.getCorpId(), course);
    		if(c!=null) {
    			Dksb d = dksbService.getById(c.getDksbId());
    			throw new BadRequestException(getRepeatInfo(c.getEventdate(),c.getGrade(),c.getClasz(),c.getCoursetime(),d.getStatus()));
    		}
    	}
        return new ResponseEntity<>(HttpStatus.OK);
    }
    
    @Log("编辑申报:创建或者修改操作")
    @ApiOperation("编辑申报:创建或者修改操作")
    @PutMapping
    //@AnonymousAccess
    public ResponseEntity<Object> edit(@Validated @RequestBody Dksb resources) {
    	//检查重复申报，不能跟提交的，审批中,审批通过的有重复 0-未提交；1-审批中；2-已通过；3-已驳回；4-已取消
    	for(DksbCourse course: resources.getCourses()) {
    		DksbCourse c = dksbCourseService.checkRepeat(resources.getCorpId(), course);
    		if(c!=null) {
    			Dksb d = dksbService.getById(c.getDksbId());
    			throw new BadRequestException(getRepeatInfo(c.getEventdate(),c.getGrade(),c.getClasz(),c.getCoursetime(),d.getStatus()));
    		}
    	}
        dksbService.saveOrUpdate(resources);
        //删除旧记录
        dksbCourseService.remove(new LambdaQueryWrapper<DksbCourse>().eq(DksbCourse::getDksbId, resources.getId()));
        //保存课程子集
        resources.getCourses().stream().forEach((DksbCourse course) ->{
        	course.setId(null);
        	course.setDksbId(resources.getId());
        	dksbCourseService.save(course);
        });
        
        return new ResponseEntity<>(ResultData.data(resources),HttpStatus.OK);
    }
    
    /**
     * 格式化消息
     * */
    private String getRepeatInfo(LocalDate eventdate,String grade,String clasz,String coursetime,Integer status ) {
//    	DksbConsts.gradeMap.get(grade);
    	return String.format("该代课记录已存在,记录:%s %s %s %s 状态：%s ",
    			eventdate,
    			DksbConsts.gradeMap.get(grade),
    			DksbConsts.claszMap.get(clasz),
    			DksbConsts.coursetimeMap.get(coursetime),
    			DksbConsts.statusMap.get(status)
    			);
    }
    
    @Log("批量设置申报状态")
    @ApiOperation("批量设置申报状态")
    @PutMapping(value="status/{status}")
    //@AnonymousAccess
    public ResponseEntity<Object> getDksb(@PathVariable Integer status, @RequestBody Set<String> thirdNos) {
    	JwtUser jwtUser = (JwtUser) wxUserService.loadUserByUsername(SecurityUtils.getUsername());
    	
    	Wrapper<Dksb> updateWrapper = new LambdaUpdateWrapper<Dksb>()
    			.in(Dksb::getThirdNo, thirdNos)
    			.set(Dksb::getStatus, status)
    			.set(Dksb::getAuditUserid, jwtUser.getUserId())
    			.set(Dksb::getAuditNotes, "非流程审批，后台统一操作");
    	dksbService.update(updateWrapper);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @ForbidSubmit
    @Log("删除申报")
    @ApiOperation("删除申报")
    @DeleteMapping
    //@AnonymousAccess
    public ResponseEntity<Object> delete(@RequestBody Set<Long> ids) {
    	ids.forEach(id->{
			dksbService.removeById(id);
			dksbCourseService.remove(new LambdaQueryWrapper<DksbCourse>().eq(DksbCourse::getDksbId, id));
		});
        return new ResponseEntity<>(HttpStatus.OK);
    }

}
